# python 四大容器（数据结构）

# 列表 list
# 特点： 有序、里面的元素不唯一可以重复、可变的、元素的类型可以不唯一
# 跟 数组类似 可以存 很多”数“ 相当于数据的一个集合
# 一个班 有 40 名同学，需要记录他们的成绩
# ctrl alt L
score1 = 80
score2 = 90
score3 = 100
score4 = 70
score5 = 99
score6 = 59

# [] 定义一个list
list1 = [1, 2, 3, 4, 5]
print(list1, type(list1))

score_list = [80, 90, 100, 70, 99, 59]
score_new_list = [80, "80", "100", 99.9]

# 取 元素
print(score_list[2])  # 100
print(score_list[4])  # 99
# 传入的索引 不能超过 list 的长度
# print(score_list[6])  # list index out of range

# list 还支持 负数索引 即表示 从右往左数 例如： -1 表示 从右往左第一个元素
print(score_list[5])  # 59
print(score_list[-1])  # 59

# list 倒转
# list 切片 可以传入 三个数 a:b:c
# a: 起始位置 如果不写 默认从第一位开始
# b: 结束位置 如果不写 默认全部取完
# c: 步长 默认为 1
print(score_list[-1::-1])  # 59 99 70 100 90 80
print(score_list[-1::-2])  # 59 70 90

# 90 100 70
# 90 的索引 为1 所以起始位置写1
# 70 的索引 为3 但是 左闭右开 结束位置得写 3+1 = 4
# 步长不指定可以省略 默认为1
print(score_list[1:4])

# 100 59
print(score_list[2::3])

# 增加一个元素
# 使用 append方法 默认将新的元素加到最后
score_list.append(75)
print(score_list)

# insert 方法 需要传入两个参数 index value
# 表示 在 index的位置 插入 value，index之后的元素 自动右移
score_list.insert(2, 95)
print(score_list)

# 修改一个元素
# 直接通过索引修改赋值即可
score_list[3] = 98
print(score_list)

# 删除一个元素
# pop 方法会弹出最后一个元素
score_list.pop()
print(score_list)
score_list.pop()
print(score_list)

# 也可以使用 del 关键字 指定一个元素删除
del score_list[1]
print(score_list)

# 查找一个元素
print(score_list.index(99))
# 如果没找到 会直接抛出异常
# print(score_list.index(100))
print(score_list.index(95))

# 排序
list2 = [2, 4, 7, 5, 4, 6, 1, 8, 10, 9]
# 直接调用 sort 方法 即可对list 从小到大排序
# 如果要从大到小排序 则指定 参数 reverse = True
list2.sort(reverse=True)
print(list2)

# 多维list
list3 = [1, 2, 3, 4]
list4 = [4, 5, 6, 7]
# 二维list
list5 = [list3, list4]
print(list5)
print(list5[1][1])  # 5

print("*" * 100)
# tuple 元组
# 特点：有序、不可变、元素值 和 类型 可以不唯一
# 定义一个元组
tuple1 = (1, 2, 2, 3)
print(tuple1, type(tuple1))

# 取一个元素 可以通过下标 取里面的元素
print(tuple1[1])

# 元组是"不可变的"(这里的不可变 实际上指的是 元素每个元素的指向不可变)，里面的元素不支持修改
# 元素在定义的时候就确定了
# 如果修改会抛出 'tuple' object does not support item assignment 错误
# tuple1[1] = 4


# 元组 "可变" example
listA = [1, 2, 3]
tuple2 = (1, 2, 3, listA)
print(tuple2)
tuple2[3][1] = 20
print(tuple2)

# 如果要定义只有一个元素的元组 记得加上一个逗号
tuple3 = (1,)
print(tuple3, type(tuple3))

# 字典 dict
# 特点：无序、可变、不能存在相同的key，可以存在相同的value、查询速度非常快（不会随着元素的增多而改变查询速度）
# 定义一个字典 使用 花括号 定一个字典 字典里面每个元素 都是 k-v键值对，key必须是不可变的
dict1 = {"key1": "value1", "key2": "value2"}
print(dict1, type(dict1))

# 取 value2 只能通过 key 去取 value ，不能使用索引
print(dict1["key2"])
# 删
dict1.pop("key1")
print(dict1)
# 改
dict1["key2"] = "newValue2"
print(dict1)
# 增加
dict1["newKey1"] = "newValue1"
print(dict1)
dict1["newKey2"] = "newValue2"
print(dict1)

# 可变对象不能最为 dict 的 key
listKey = [1, 2, 3]
# dict2 = {listKey: "listValue"}

tupleKey = (1, 2, 3)
dict3 = {tupleKey, "tupleValue"}

print("*" * 100)
# 集合 set
# 类似我们数学中的集合
# 特点：元素唯一、无序、可变的

# 定义一个集合
set1 = {1, 2, 3, 4}
print(set1, type(set1))  #

# 集合 会对元素自动去重
set2 = {1, 2, 2, 3, 3, 4, 3, 4}
print(set2)

# 不能赋值 修改 'set' object does not support item assignment
# set2[2] = 20
# print(set2)

# 不支持索引 'set' object does not support indexing
# print(set2[2])

# 删除一个指定的元素 不是通过索引 删除
set2.remove(4)
print(set2)

# 运算
set3_1 = {1, 2, 3, 4, 5}
set3_2 = {4, 5, 6, 7, 8}

# 交集
print(set3_1 & set3_2)

# 并集
print(set3_1 | set3_2)

# # 差集
# print(set3_1 - set3_2)
#
# # 补集
# print(set3_2 - set3_1)
